/**
 * 
 */
package com.db.stockexchange.client;

import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author Rayman
 * Represents logic of client
 */
public class ClientEngine {
	ClientPresenter presenter;
	// linked - in order to iterate stocks in insertion order 
	// key - order ID
	HashMap<Integer, Stock> stocks = new LinkedHashMap<Integer, Stock>();
	int maxId = 0;
	
	MessageHandler handler;
	Logger logger;
	
	public ClientEngine(String clientID, InetAddress address, int port, ClientPresenter presenter) throws IOException {
		this.presenter = presenter;
		handler = new MessageHandler(this, clientID, address, port);
		logger = Logger.getLogger(this.getClass().getName());
	}
	
	public void addStock(Stock stock) {
		stock.setId(++maxId);
		stocks.put(stock.getId(), stock);
		handler.sendNewOrder(stock);
	}
	
	public List<Stock> getStocks() {
		return Collections.unmodifiableList(new ArrayList<Stock>(stocks.values()));
	}

	public void reject(String reasonDetail) {
		presenter.reject(reasonDetail);
		logger.fine("Order is rejected. Detail: " + reasonDetail);	
	}

	public void reject(int orderID, String reasonDetail) {
		Stock stock = stocks.get(orderID);
		if (stock == null)
			logger.fine(String.format("Stock with orderID <%s> is not found", orderID));
		else {
			stock.setState(StockState.REJECTED);
			presenter.refreshStockList();
			logger.fine(String.format("Order <%s> is rejected. Detail: %s", orderID, reasonDetail));
		}
	}

	public void ack(int orderID) {
		Stock stock = stocks.get(orderID);
		if (stock == null)
			logger.fine(String.format("Stock with orderID <%s> is not found", orderID));
		else {
			stock.setState(StockState.NEW);
			presenter.refreshStockList();
			logger.fine(String.format("Order <%s> is acknowledged", orderID));		
		}
	}

	public void fill(int orderID, int cumQuantity, int leavesQuantity, StockState state) {
		Stock stock = stocks.get(orderID);
		if (stock == null)
			logger.fine(String.format("Stock with orderID <%s> is not found", orderID));
		else {
			stock.setFilledShareNumber(cumQuantity);
			stock.setLeftShareNumber(leavesQuantity);
			stock.setState(state);
			presenter.refreshStockList();
			logger.fine(String.format("Order <%s> is filled. Filled share number is %d," +
					" left share number is %d, state is <%s>", orderID, cumQuantity, leavesQuantity, state));
		}
	}	
	
	public void close() {
		handler.close();
	}
}
